package PortAudioAda.Win_WaveFormat is

   type PaWinWaveFormatChannelMask is new IC.unsigned_long;

   -----------------------------------------------------------------------------
   --  Speaker Positions:
   PAWIN_SPEAKER_FRONT_LEFT
     : constant PaWinWaveFormatChannelMask := 16#0000_0001#;
   PAWIN_SPEAKER_FRONT_RIGHT
     : constant PaWinWaveFormatChannelMask := 16#0000_0002#;
   PAWIN_SPEAKER_FRONT_CENTER
     : constant PaWinWaveFormatChannelMask := 16#0000_0004#;
   PAWIN_SPEAKER_LOW_FREQUENCY
     : constant PaWinWaveFormatChannelMask := 16#0000_0008#;
   PAWIN_SPEAKER_BACK_LEFT
     : constant PaWinWaveFormatChannelMask := 16#0000_0010#;
   PAWIN_SPEAKER_BACK_RIGHT
     : constant PaWinWaveFormatChannelMask := 16#0000_0020#;
   PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER
     : constant PaWinWaveFormatChannelMask := 16#0000_0040#;
   PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER
     : constant PaWinWaveFormatChannelMask := 16#0000_0080#;
   PAWIN_SPEAKER_BACK_CENTER
     : constant PaWinWaveFormatChannelMask := 16#0000_0100#;
   PAWIN_SPEAKER_SIDE_LEFT
     : constant PaWinWaveFormatChannelMask := 16#0000_0200#;
   PAWIN_SPEAKER_SIDE_RIGHT
     : constant PaWinWaveFormatChannelMask := 16#0000_0400#;
   PAWIN_SPEAKER_TOP_CENTER
     : constant PaWinWaveFormatChannelMask := 16#0000_0800#;
   PAWIN_SPEAKER_TOP_FRONT_LEFT
     : constant PaWinWaveFormatChannelMask := 16#0000_1000#;
   PAWIN_SPEAKER_TOP_FRONT_CENTER
     : constant PaWinWaveFormatChannelMask := 16#0000_2000#;
   PAWIN_SPEAKER_TOP_FRONT_RIGHT
     : constant PaWinWaveFormatChannelMask := 16#0000_4000#;
   PAWIN_SPEAKER_TOP_BACK_LEFT
     : constant PaWinWaveFormatChannelMask := 16#0000_8000#;
   PAWIN_SPEAKER_TOP_BACK_CENTER
     : constant PaWinWaveFormatChannelMask := 16#0001_0000#;
   PAWIN_SPEAKER_TOP_BACK_RIGHT
     : constant PaWinWaveFormatChannelMask := 16#0002_0000#;

   --  Bit mask locations reserved for future use
   PAWIN_SPEAKER_RESERVED
     : constant PaWinWaveFormatChannelMask := 16#7FFC_0000#;

   --  Used to specify that any possible permutation of speaker configurations
   PAWIN_SPEAKER_ALL
     : constant PaWinWaveFormatChannelMask := 16#8000_0000#;

   --  DirectSound Speaker Config
   PAWIN_SPEAKER_DIRECTOUT
     : constant PaWinWaveFormatChannelMask := 0;
   PAWIN_SPEAKER_MONO
     : constant PaWinWaveFormatChannelMask :=
       PAWIN_SPEAKER_FRONT_CENTER;
   PAWIN_SPEAKER_STEREO
     : constant PaWinWaveFormatChannelMask :=
       (PAWIN_SPEAKER_FRONT_LEFT or PAWIN_SPEAKER_FRONT_RIGHT);
   PAWIN_SPEAKER_QUAD
     : constant PaWinWaveFormatChannelMask :=
       (PAWIN_SPEAKER_FRONT_LEFT or
            PAWIN_SPEAKER_FRONT_RIGHT or
              PAWIN_SPEAKER_BACK_LEFT  or
                PAWIN_SPEAKER_BACK_RIGHT);
   PAWIN_SPEAKER_SURROUND
     : constant PaWinWaveFormatChannelMask :=
       (PAWIN_SPEAKER_FRONT_LEFT or
            PAWIN_SPEAKER_FRONT_RIGHT or
              PAWIN_SPEAKER_FRONT_CENTER or
                PAWIN_SPEAKER_BACK_CENTER);
   PAWIN_SPEAKER_5POINT1
     : constant PaWinWaveFormatChannelMask :=
       (PAWIN_SPEAKER_FRONT_LEFT or
            PAWIN_SPEAKER_FRONT_RIGHT or
              PAWIN_SPEAKER_FRONT_CENTER or
                PAWIN_SPEAKER_LOW_FREQUENCY or
                  PAWIN_SPEAKER_BACK_LEFT or
                    PAWIN_SPEAKER_BACK_RIGHT);
   PAWIN_SPEAKER_7POINT1
     : constant PaWinWaveFormatChannelMask :=
       (PAWIN_SPEAKER_FRONT_LEFT or
            PAWIN_SPEAKER_FRONT_RIGHT or
              PAWIN_SPEAKER_FRONT_CENTER or
                PAWIN_SPEAKER_LOW_FREQUENCY or
                  PAWIN_SPEAKER_BACK_LEFT or
                    PAWIN_SPEAKER_BACK_RIGHT or
                      PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER or
                        PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER);
   PAWIN_SPEAKER_5POINT1_SURROUND
     : constant PaWinWaveFormatChannelMask :=
       (PAWIN_SPEAKER_FRONT_LEFT or
            PAWIN_SPEAKER_FRONT_RIGHT or
              PAWIN_SPEAKER_FRONT_CENTER or
                PAWIN_SPEAKER_LOW_FREQUENCY or
                  PAWIN_SPEAKER_SIDE_LEFT or
                    PAWIN_SPEAKER_SIDE_RIGHT);
   PAWIN_SPEAKER_7POINT1_SURROUND
     : constant PaWinWaveFormatChannelMask :=
       (PAWIN_SPEAKER_FRONT_LEFT or
            PAWIN_SPEAKER_FRONT_RIGHT or
              PAWIN_SPEAKER_FRONT_CENTER or
                PAWIN_SPEAKER_LOW_FREQUENCY or
                  PAWIN_SPEAKER_BACK_LEFT or
                    PAWIN_SPEAKER_BACK_RIGHT or
                      PAWIN_SPEAKER_SIDE_LEFT or
                        PAWIN_SPEAKER_SIDE_RIGHT);

   --  According to the Microsoft documentation:
   --  The following are obsolete 5.1 and 7.1 settings (they lack side
   --  speakers).  Note this means that the default 5.1 and 7.1 settings
   --  (KSAUDIO_SPEAKER_5POINT1 and KSAUDIO_SPEAKER_7POINT1 are similarly
   --  obsolete but are unchanged for compatibility reasons).
   PAWIN_SPEAKER_5POINT1_BACK
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_5POINT1;
   PAWIN_SPEAKER_7POINT1_WIDE
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_7POINT1;

   --  DVD Speaker Positions
   PAWIN_SPEAKER_GROUND_FRONT_LEFT
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_FRONT_LEFT;
   PAWIN_SPEAKER_GROUND_FRONT_CENTER
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_FRONT_CENTER;
   PAWIN_SPEAKER_GROUND_FRONT_RIGHT
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_FRONT_RIGHT;
   PAWIN_SPEAKER_GROUND_REAR_LEFT
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_BACK_LEFT;
   PAWIN_SPEAKER_GROUND_REAR_RIGHT
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_BACK_RIGHT;
   PAWIN_SPEAKER_TOP_MIDDLE
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_TOP_CENTER;
   PAWIN_SPEAKER_SUPER_WOOFER
     : constant PaWinWaveFormatChannelMask := PAWIN_SPEAKER_LOW_FREQUENCY;

   --  PaWinWaveFormat is defined here to provide compatibility with compilation
   --  environments which don't have headers defining WAVEFORMATEXTENSIBLE
   --  (e.g. older versions of MSVC, Borland C++ etc.
   --
   --  The fields for WAVEFORMATEX and WAVEFORMATEXTENSIBLE are declared as an
   --  unsigned char array here to avoid clients who include this file having a
   --  dependency on windows.h and mmsystem.h, and also to to avoid having to
   --  write separate packing pragmas for each compiler.
   PAWIN_SIZEOF_WAVEFORMATEX
     : constant := 18;
   PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE
     : constant := (PAWIN_SIZEOF_WAVEFORMATEX + 22);

   type PaWinWaveFormat is
      record
         fields
           : aliased IC.char_array (1 .. PAWIN_SIZEOF_WAVEFORMATEXTENSIBLE);

         --  ensure that compiler aligns struct to DWORD
         extraLongForAlignment : aliased IC.unsigned_long;
      end record;
   pragma Convention (C, PaWinWaveFormat);

   --
   --  WAVEFORMATEXTENSIBLE fields:
   --
   --  union  {
   --     WORD  wValidBitsPerSample;
   --     WORD  wSamplesPerBlock;
   --     WORD  wReserved;
   --  } Samples;
   --  DWORD  dwChannelMask;
   --  GUID  SubFormat;
   PAWIN_INDEXOF_WVALIDBITSPERSAMPLE
     : constant := (PAWIN_SIZEOF_WAVEFORMATEX + 0);
   PAWIN_INDEXOF_DWCHANNELMASK
     : constant := (PAWIN_SIZEOF_WAVEFORMATEX + 2);
   PAWIN_INDEXOF_SUBFORMAT
     : constant := (PAWIN_SIZEOF_WAVEFORMATEX + 6);

   --  Valid values to pass for the waveFormatTag PaWin_InitializeWaveFormatEx
   --  and PaWin_InitializeWaveFormatExtensible functions below. These must
   --  match the standard Windows WAVE_FORMAT_ * values.
   PAWIN_WAVE_FORMAT_PCM             : constant := 1;
   PAWIN_WAVE_FORMAT_IEEE_FLOAT      : constant := 3;
   PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF : constant := 16#0092#;
   PAWIN_WAVE_FORMAT_WMA_SPDIF       : constant := 16#0164#;

   -----------------------------------------------------------------------------
   --  returns PAWIN_WAVE_FORMAT_PCM or PAWIN_WAVE_FORMAT_IEEE_FLOAT depending
   --  on the sampleFormat parameter.
   function PaWin_SampleFormatToLinearWaveFormatTag
     (sampleFormat : PaSampleFormat) return Integer;
   pragma Import (C,
                  PaWin_SampleFormatToLinearWaveFormatTag,
                  "PaWin_SampleFormatToLinearWaveFormatTag");

   -----------------------------------------------------------------------------
   --  Use the following two functions to initialize the waveformat structure.
   procedure PaWin_InitializeWaveFormatEx
     (waveFormat    : access PaWinWaveFormat;
      numChannels   : Integer;
      sampleFormat  : PaSampleFormat;
      waveFormatTag : Integer;
      sampleRate    : Long_Float);
   pragma Import (C,
                  PaWin_InitializeWaveFormatEx,
                  "PaWin_InitializeWaveFormatEx");

   procedure PaWin_InitializeWaveFormatExtensible
     (waveFormat    : access PaWinWaveFormat;
      numChannels   : Integer;
      sampleFormat  : PaSampleFormat;
      waveFormatTag : Integer;
      sampleRate    : Long_Float;
      channelMask   : PaWinWaveFormatChannelMask);
   pragma Import (C,
                  PaWin_InitializeWaveFormatExtensible,
                  "PaWin_InitializeWaveFormatExtensible");

   -----------------------------------------------------------------------------
   --  Map a channel count to a speaker channel mask
   function PaWin_DefaultChannelMask (numChannels : Integer)
                                      return PaWinWaveFormatChannelMask;
   pragma Import (C, PaWin_DefaultChannelMask, "PaWin_DefaultChannelMask");

end PortAudioAda.Win_WaveFormat;
